#include <REGX52.H>

// 注：LCD1602模块驱动代码较为复杂，不需要完全搞懂原理，会使用即可
// 下面简要介绍需要用到的封装函数，以具体的使用为例

//		void main()
//		{
//			LCD_Init();											//这是LCD1602模块的初始化函数，在主函数必须调用一次
//			LCD_ShowChar(1,1,'A');					//在1行1列显示字符A
//			LCD_ShowString(1,3,"Hello");		//在1行3列显示字符串Hello
//			LCD_ShowNum(1,9,66,2);					//在1行9列显示数字66，长度为2
//			LCD_ShowSignedNum(1,12,-88,2);	//在1行12列显示有符号数字-88，长度为2
//			LCD_ShowHexNum(2,1,0xA5,2);			//在2行1列显示十六进制数字0xA5，长度为2
//			LCD_ShowBinNum(2,4,0xA5,8);			//在2行4列显示二进制数字0xA5，长度为8
//			LCD_ShowChar(2,13,0xDF);				//在2行13列显示编码为0xDF的字符
//			LCD_ShowChar(2,14,'C');					//在2行14列显示字符C
//		}

// 引脚定义：
sbit LCD_RS=P2^6;
sbit LCD_RW=P2^5;
sbit LCD_EN=P2^7;
#define LCD_DataPort P0

/*******************************************************************************
* 函 数 名     : LCD1602延时函数，12MHz调用可延时1ms
* 函数功能		 : 提供延时
*******************************************************************************/
void LCD_Delay()
{
	unsigned char i, j;

	i = 2;
	j = 239;
	do
	{
		while (--j);
	} while (--i);
}

/*******************************************************************************
* 函 数 名     : LCD1602写命令
* 函数功能		 : 写命令
*******************************************************************************/
void LCD_WriteCommand(unsigned char Command)
{
	LCD_RS=0;
	LCD_RW=0;
	LCD_DataPort=Command;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/*******************************************************************************
* 函 数 名     : LCD1602写数据
* 函数功能		 : 写数据
*******************************************************************************/
void LCD_WriteData(unsigned char Data)
{
	LCD_RS=1;
	LCD_RW=0;
	LCD_DataPort=Data;
	LCD_EN=1;
	LCD_Delay();
	LCD_EN=0;
	LCD_Delay();
}

/*******************************************************************************
* 函 数 名     : LCD1602设置光标位置
* 函数功能		 : Line 行位置，范围：1~2 Column 列位置，范围：1~16
*******************************************************************************/
void LCD_SetCursor(unsigned char Line,unsigned char Column)
{
	if(Line==1)
	{
		LCD_WriteCommand(0x80|(Column-1));
	}
	else if(Line==2)
	{
		LCD_WriteCommand(0x80|(Column-1+0x40));
	}
}

/*******************************************************************************
* 函 数 名     : LCD1602初始化函数
* 函数功能		 : 初始化
*******************************************************************************/
void LCD_Init()
{
	LCD_WriteCommand(0x38);//八位数据接口，两行显示，5*7点阵
	LCD_WriteCommand(0x0c);//显示开，光标关，闪烁关
	LCD_WriteCommand(0x06);//数据读写操作后，光标自动加一，画面不动
	LCD_WriteCommand(0x01);//光标复位，清屏
}

/*******************************************************************************
* 函 数 名     : 在LCD1602指定位置上显示一个字符
* 函数功能		 : Line 行位置，范围：1~2 Column 列位置，范围：1~16
*******************************************************************************/
void LCD_ShowChar(unsigned char Line,unsigned char Column,char Char)
{
	LCD_SetCursor(Line,Column);
	LCD_WriteData(Char);
}

/*******************************************************************************
* 函 数 名     : 在LCD1602指定位置开始显示所给字符串
* 函数功能		 : Line 起始行位置，范围：1~2 Column 起始列位置，范围：1~16
*******************************************************************************/
void LCD_ShowString(unsigned char Line,unsigned char Column,char *String)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=0;String[i]!='\0';i++)
	{
		LCD_WriteData(String[i]);
	}
}

/*******************************************************************************
* 函 数 名     : 返回值=X的Y次方
* 函数功能		 : 如上
*******************************************************************************/
int LCD_Pow(int X,int Y)
{
	unsigned char i;
	int Result=1;
	for(i=0;i<Y;i++)
	{
		Result*=X;
	}
	return Result;
}

/*******************************************************************************
* 函 数 名     : 在LCD1602指定位置开始显示所给数字
* 函数功能		 : 
									Line 起始行位置，范围：1~2
									Column 起始列位置，范围：1~16
									Number 要显示的数字，范围：0~65535
									Length 要显示数字的长度，范围：1~5
*******************************************************************************/
void LCD_ShowNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(10,i-1)%10+'0');
	}
}

/*******************************************************************************
* 函 数 名     : 在LCD1602指定位置开始以有符号十进制显示所给数字
* 函数功能		 : 
									Line 起始行位置，范围：1~2
									Column 起始列位置，范围：1~16
									Number 要显示的数字，范围：-32768~32767
									Length 要显示数字的长度，范围：1~5
*******************************************************************************/
void LCD_ShowSignedNum(unsigned char Line,unsigned char Column,int Number,unsigned char Length)
{
	unsigned char i;
	unsigned int Number1;
	LCD_SetCursor(Line,Column);
	if(Number>=0)
	{
		LCD_WriteData('+');
		Number1=Number;
	}
	else
	{
		LCD_WriteData('-');
		Number1=-Number;
	}
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number1/LCD_Pow(10,i-1)%10+'0');
	}
}

/*******************************************************************************
* 函 数 名     : 在LCD1602指定位置开始以有符号十进制显示所给数字
* 函数功能		 : 
									Line 起始行位置，范围：1~2
									Column 起始列位置，范围：1~16
									Number 要显示的数字，范围：0~0xFFFF
									Length 要显示数字的长度，范围：1~4
*******************************************************************************/
void LCD_ShowHexNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i,SingleNumber;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		SingleNumber=Number/LCD_Pow(16,i-1)%16;
		if(SingleNumber<10)
		{
			LCD_WriteData(SingleNumber+'0');
		}
		else
		{
			LCD_WriteData(SingleNumber-10+'A');
		}
	}
}

/*******************************************************************************
* 函 数 名     : 在LCD1602指定位置开始以二进制显示所给数字
* 函数功能		 : 
									Line 起始行位置，范围：1~2
									Column 起始列位置，范围：1~16
									Number 要显示的数字，范围：0~1111 1111 1111 1111
									Length 要显示数字的长度，范围：1~16
*******************************************************************************/
void LCD_ShowBinNum(unsigned char Line,unsigned char Column,unsigned int Number,unsigned char Length)
{
	unsigned char i;
	LCD_SetCursor(Line,Column);
	for(i=Length;i>0;i--)
	{
		LCD_WriteData(Number/LCD_Pow(2,i-1)%2+'0');
	}
}
